class GameService {
  constructor() {
    this.games = new Map();
    this.CARD_TYPES = ['Sunny', 'Rainy', 'Cloudy', 'Rainbow'];
    this.NUMBERS = Array.from({length: 13}, (_, i) => i + 1);
  }

  createGame(roomNumber, players) {
    // 创建基础游戏对象
    const game = {
      roomNumber,
      players,
      currentRound: 1,
      currentTurn: 0,
      maxSuit: null,
      deck: this.createDeck(),
      playedCards: [],
      playerHands: new Map(),
      playerPredictions: new Map(),
      scores: new Map(players.map(player => [player, 0])),
      roundScores: new Map(players.map(player => [player, 0])),
      status: 'waiting_dealCards'
    };
    
    this.games.set(roomNumber, game);
    return game;
  }

  createDeck() {
    let deck = [];
    
    // 创建普通牌
    this.CARD_TYPES.forEach(type => {
      this.NUMBERS.forEach(number => {
        deck.push({
          type,
          number
        });
      });
    });
    
    // 添加Win牌
    for (let i = 0; i < 4; i++) {
      deck.push({
        type: 'Win',
        number: null
      });
    }
    
    // 添加Loss牌
    for (let i = 0; i < 4; i++) {
      deck.push({
        type: 'Loss',
        number: null
      });
    }
    
    return this.shuffleDeck(deck);
  }

  shuffleDeck(deck) {
    // Fisher-Yates 洗牌算法
    for (let i = deck.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [deck[i], deck[j]] = [deck[j], deck[i]];
    }
    return deck;
  }

  dealCards(game) {
    // 每轮开始时，重新发牌
    // 计算本轮每个玩家应得到的牌数
    const cardsPerPlayer = 2 * (game.currentRound - 1) + 1;
    
    // 清空所有玩家手牌
    game.playerHands = new Map();
    game.players.forEach(player => {
      game.playerHands.set(player, []);
    });
    
    // 发牌
    for (let i = 0; i < cardsPerPlayer; i++) {
      game.players.forEach(player => {
        const card = game.deck.pop();
        if (card) {
          const playerHand = game.playerHands.get(player);
          playerHand.push(card);
        }
      });
    }
    
    // 设置状态为等待预测
    game.status = 'waiting_predictions';
    game.playerPredictions = new Map();
    
    return game;
  }

  determineMaxSuit(game) {
    // 抽取一张牌来决定最大类型
    const card = game.deck.pop();
    
    if (card.type === 'Win') {
      // Win牌由优先出牌者指定最大类型，先将牌放回牌堆
      game.deck.push(card);
      game.maxSuit = 'pending'; // 等待优先出牌者指定
    } else if (card.type === 'Loss') {
      // Loss牌情况下忽略所有类型
      game.deck.push(card);
      game.maxSuit = 'none';
    } else {
      // 普通牌直接确定最大类型
      game.maxSuit = card.type;
      game.deck.push(card);
    }
    
    return game;
  }

  setMaxSuit(game, playerId, selectedType) {
    // 仅当maxSuit为pending且是优先出牌者时才能设置
    if (game.maxSuit === 'pending' && playerId === this.getCurrentPlayer(game)) {
      if (this.CARD_TYPES.includes(selectedType)) {
        game.maxSuit = selectedType;
        return true;
      }
    }
    return false;
  }

  playCard(gameId, playerId, cardIndex) {
    const game = this.games.get(gameId);
    if (!game) throw new Error('Game not found');

    // 验证是否轮到该玩家出牌
    if (this.getCurrentPlayer(game) !== playerId) {
      throw new Error('Not your turn');
    }

    // 获取玩家手牌
    const playerHand = game.playerHands.get(playerId);
    if (!playerHand || cardIndex >= playerHand.length) {
      throw new Error('Invalid card');
    }

    // 打出卡牌
    const card = playerHand.splice(cardIndex, 1)[0];
    game.playedCards.push({
      playerId,
      card,
      timestamp: Date.now() // 记录出牌时间，用于同点数时比较先后顺序
    });

    // 如果所有玩家都出牌了，进行结算
    if (game.playedCards.length === game.players.length) {
      this.settleTurn(game);
    }

    return game;
  }

  compareCards(game, cardA, cardB) {
    // 特殊牌比较
    if (cardA.card.type === 'Win' && cardB.card.type === 'Win') {
      // 两张都是WIN牌时，按出牌顺序决定胜负
      return cardA.timestamp < cardB.timestamp ? -1 : 1;
    }
    if (cardA.card.type === 'Win') return -1;
    if (cardB.card.type === 'Win') return 1;
    if(cardA.card.type === 'Loss' && cardB.card.type === 'Loss'){
      // 两张都是Loss牌时，先出的Loss牌更小
      return cardA.timestamp < cardB.timestamp ? 1 : -1;
    }

    if (cardA.card.type === 'Loss') return 1;
    if (cardB.card.type === 'Loss') return -1;

    // Loss牌情况下，忽略类型只比大小
    if (game.maxSuit === 'none') {
      if (cardA.card.number === cardB.card.number) {
        return cardA.timestamp < cardB.timestamp ? -1 : 1;
      }
      return cardA.card.number > cardB.card.number ? -1 : 1;
    }

    // 普通情况
    const aIsMax = cardA.card.type === game.maxSuit;
    const bIsMax = cardB.card.type === game.maxSuit;

    // 最大类型比较
    if (aIsMax && !bIsMax) return -1; // a大
    if (!aIsMax && bIsMax) return 1;

    // 同为非王牌的普通类型
    if(aIsMax == bIsMax){
      if (cardA.card.number === cardB.card.number) {
        // 同点数比较出牌顺序
        return cardA.timestamp < cardB.timestamp ? -1 : 1;
      }
      return cardA.card.number > cardB.card.number ? -1 : 1;
    }
  }

  // 辅助方法：获取当前应该出牌的玩家
  getCurrentPlayer(game) {
    const playerCount = game.players.length;
    const turnOrder = game.currentRound % playerCount; // 0, 1, 2 轮转
    const currentTurnIndex = (turnOrder + game.currentTurn) % playerCount;
    return game.players[currentTurnIndex];
  }

  // 辅助方法：结算当前回合
  settleTurn(game) {
    // 检查最大类型是否已确定
    if (game.maxSuit === 'pending') {
      throw new Error('Cannot settle turn while maxSuit is pending');
    }

    // 检查是否所有玩家都已出牌
    if (game.playedCards.length !== game.players.length) {
      throw new Error('Not all players have played their cards');
    }
    
    // 对出的牌进行排序并找出获胜者
    const sortedCards = [...game.playedCards].sort((a, b) => this.compareCards(game, a, b));
    const winner = sortedCards[0].playerId;
    
    
    const currentScore = game.roundScores.get(winner) || 0;
    console.log('当前得分:', currentScore);
    game.roundScores.set(winner, currentScore + 1);
    console.log('更新后得分:', game.roundScores.get(winner));
    // 清空出牌区
    game.playedCards = [];
    
    // 更新回合数
    game.currentTurn++;
    
    // 如果本轮所有回合都完成，进入下一轮
    const cardsPerPlayer = 2 * (game.currentRound - 1) + 1;
    if (game.currentTurn >= cardsPerPlayer) {      
      this.nextRound(game);
    }

    return game;
  }

  nextRound(game) {
    // 根据预测结果和实际获胜次数判断得分情况
    game.players.forEach(playerId => {
      const currentScore = game.scores.get(playerId);
      const roundScore = game.roundScores.get(playerId);
      const prediction = game.playerPredictions.get(playerId);
      
      // 若预测正确，则该玩家得分 + 预测值
      // 若预测错误，则该玩家得分 - 预测值与实际值的差值
      if(prediction === roundScore) {
        game.scores.set(playerId, currentScore + roundScore);
      } else {
        const diff = Math.abs(prediction - roundScore);
        game.scores.set(playerId, currentScore - diff);
      }
      
      // 重置本轮数据
      game.playerPredictions.set(playerId, 0);
      game.roundScores.set(playerId, 0);
    });

    // 进入下一轮
    game.currentRound++;
    game.currentTurn = 0;
    game.playedCards = [];
    game.playerPredictions.clear(); // 清空上一轮的预测

    // 检查是否达到游戏结束条件
    if (this.isGameOver(game)) {
      return this.endGame(game);
    }

    // 准备新一轮
    game.deck = this.createDeck(); // 重新洗牌
    this.dealCards(game); // 发牌
    this.determineMaxSuit(game); // 确定最大类型
    game.status = 'waiting_predictions'; // 设置游戏状态为等待预测

    return game;
  }

  isGameOver(game) {
    // 计算下一轮每个玩家需要的牌数
    const nextRoundCards = 2 * game.currentRound + 1; // 2*(currentRound-1)+1 的下一轮
    const totalCardsNeeded = nextRoundCards * game.players.length;
    
    // 如果下一轮需要的总牌数超过59（保留一张用于确定最大类型），则游戏结束
    return totalCardsNeeded > 59;
  }

  endGame(game) {
    game.status = 'finished';
    
    // 计算最终排名
    const rankings = [...game.players]
      .map(playerId => ({
        playerId,
        score: game.scores.get(playerId)
      }))
      .sort((a, b) => b.score - a.score);
    
    game.rankings = rankings;
    return game;
  }

  // 获取游戏状态的辅助方法
  getGameState(roomNumber) {
    const game = this.games.get(roomNumber);
    if (!game) throw new Error('Game not found');
    
    return {
      currentRound: game.currentRound,
      currentTurn: game.currentTurn,
      maxSuit: game.maxSuit,
      playedCards: game.playedCards,
      scores: Object.fromEntries(game.scores),
      roundScores: Object.fromEntries(game.roundScores),
      currentPlayer: this.getCurrentPlayer(game),
      status: game.status || 'playing',
      rankings: game.rankings
    };
  }

  setPrediction(gameId, playerId, prediction) {
    const game = this.games.get(gameId);
    if (!game) throw new Error('Game not found');
    
    // 验证预测值的合法性
    const cardsPerPlayer = 2 * (game.currentRound - 1) + 1;
    if (prediction < 0 || prediction > cardsPerPlayer) {
      throw new Error('Invalid prediction value');
    }
    
    // 设置预测值
    game.playerPredictions.set(playerId, prediction);
    
    // 检查是否所有玩家都已完成预测
    const allPredicted = game.players.every(player => 
      game.playerPredictions.has(player)
    );
    
    // 如果所有玩家都已预测，更新游戏状态
    if (allPredicted) {
      game.status = 'playing';
      this.determineMaxSuit(game);
    }
    
    return {
      game,
      allPredicted
    };
  }

  getPlayerState(game, playerId) {
    return {
      hand: game.playerHands.get(playerId),
      prediction: game.playerPredictions.get(playerId),
      score: game.scores.get(playerId),
      roundScore: game.roundScores.get(playerId)
    };
  }

  broadcastGameState(game) {
    const baseState = {
      currentRound: game.currentRound,
      status: game.status,
      maxSuit: game.maxSuit,
      playedCards: game.playedCards,
      currentPlayer: this.getCurrentPlayer(game)
    };

    // 为每个玩家准备专属状态
    game.players.forEach(playerId => {
      const playerState = this.getPlayerState(game, playerId);
      const connection = global.connections.get(playerId);
      
      if (connection) {
        connection.send(JSON.stringify({
          type: 'GAME_STATE',
          payload: {
            ...baseState,
            ...playerState,
            // 其他玩家信息（不包含手牌）
            players: game.players.map(pid => ({
              id: pid,
              score: game.scores.get(pid),
              prediction: game.playerPredictions.get(pid),
              cardCount: game.playerHands.get(pid)?.length || 0
            }))
          }
        }));
      }
    });
  }
}

module.exports = new GameService(); 